#!/usr/bin/env python3
import aligo
from aligo import Aligo
from colorama import Fore
from typing import List
import sys
import os
import getopt


def print_usage():
    print('''Usage: alipan [ls] [[-h | --help][-u --upload][-d --download]]
    -h --help show help
    -u --upload upload file
    -d --download download file''')


def hum_convert(value):
    if value is None:
        return ''.rjust(8, ' ')
    units = ["B", "KB", "MB", "GB", "TB", "PB"]
    size = 1024.0
    for i in range(len(units)):
        if (value / size) < 1:
            o = "%.2f%s" % (value, units[i])
            return o.rjust(8, ' ')
        value = value / size


def log_files(list_file: List[aligo.BaseFile], target_file_name_show='', v=False):
    for item in list_file:
        line = ''
        if v:
            line += item.file_id
        if ' ' in item.name:
            name = '"%s%s"' % (target_file_name_show, item.name)
        else:
            name = '%s%s' % (target_file_name_show, item.name)
        if item.type == 'folder':
            line += ' d %s %s %s %s' % (hum_convert(item.size), Fore.BLUE, name, Fore.RESET)
        elif item.type == 'file':
            line += ' - %s %s %s %s' % (hum_convert(item.size), Fore.GREEN, name, Fore.RESET)
        print(line)
    print()


def aligo_list_file(ali, target_file_name='', v=False):
    target_file_name_show = target_file_name
    if target_file_name != '':
        if is_file_id(target_file_name):
            file = ali.get_file(target_file_name)
            target_file_name_show = ''
            v = True
        else:
            file = ali.get_folder_by_path(target_file_name)
            target_file_name_show += '/'
        if not file:
            print("{}Error: not found {} {}".format(Fore.RED, target_file_name, Fore.RESET))
            return
        else:
            target_file_name = file.file_id
            print("%sInDir%s: %s%s%s" % (Fore.MAGENTA, Fore.RESET, Fore.CYAN, file.name, Fore.RESET))
    else:
        target_file_name = 'root'
    list_file = ali.get_file_list(parent_file_id=target_file_name)
    if isinstance(list_file, list):
        log_files(list_file, target_file_name_show, v)
    else:
        print("no file:", list_file)


def is_file_id(i):
    return set(i) <= set('0123456789abcdef') and len(i) == 40


def aligo_download_file(ali, download_file_name):
    path_now = os.path.abspath('.')
    print("Download File:", download_file_name)
    print("This Dir:", path_now)
    if is_file_id(download_file_name):
        file = ali.get_file(download_file_name)
    else:
        file = ali.get_file_by_path(download_file_name)
    ali.download_file(file=file, local_folder=path_now)
    print()


def aligo_move_file(ali, s, t, n):
    print("Move File:%s to %s rename:%s" % (s, t, n))
    if not is_file_id(s):
        print("only support file_id")
    ali.move_file(file_id=s, to_parent_file_id=t, new_name=n)


def aligo_delete_file(ali, f):
    print("Delete File:", f)
    if is_file_id(f):
        ali.move_file_to_trash(f)
    else:
        print("only support file_id")


def aligo_list_trash(ali, v=False):
    list_file = ali.get_recyclebin_list()
    log_files(list_file, v=v)


def _get_sort_argv() -> ([], []):
    _argv, _args = [], []
    is_param = False
    for argv in sys.argv[1:]:
        if argv.startswith('-'):
            _argv.append(argv)
            is_param = True
        else:
            if is_param:
                _argv.append(argv)
                is_param = False
            else:
                _args.append(argv)
    return _argv, _args


def main():
    try:
        _argv, _args = _get_sort_argv()
        opts, args = getopt.getopt(_argv, 'vhu:d:t:s:n:i:',
                                   ['help', 'upload=', 'download=', 'target=', 'source=', 'name='])
        args = _args
        if len(opts) == 0 and len(args) == 0:
            print_usage()
            sys.exit(0)
    except getopt.GetoptError:
        print_usage()
        sys.exit(1)
    upload_file_name = ''
    download_file_name = ''
    source_file_name = ''
    target_file_name = ''
    new_file_name = ''
    config_file = 'aligo'
    _v = False
    for opt, arg in opts:
        if opt in ("-h", "--help"):
            print_usage()
            return
        elif opt in "-v":
            _v = True
        elif opt in "-i":
            config_file = arg
        elif opt in ("-u", "--upload"):
            upload_file_name = arg
        elif opt in ("-d", "--download"):
            download_file_name = arg
        elif opt in ("-s", "--source"):
            source_file_name = arg
        elif opt in ("-t", "--target"):
            target_file_name = arg
        elif opt in ("-n", "--name"):
            new_file_name = arg
        else:
            return
    print("config:%s" % (config_file))

    ali = Aligo(show=aligo.Auth._show_console, name=config_file, re_login=False)

    for arg in args:
        if arg == "ls":
            aligo_list_file(ali, target_file_name, _v)
        elif arg == "ls-trash":
            aligo_list_trash(ali, _v)
        elif arg == "rm":
            aligo_delete_file(ali, target_file_name)
        elif arg == "mv":
            aligo_move_file(ali, source_file_name, target_file_name, new_file_name)
        elif arg == "exec":
            while True:
                print(">>> ", end='')
                stdin = sys.stdin.readline().strip('\n')
                if stdin == "exit":
                    print("Bye~")
                    break
                elif stdin == "ls":
                    aligo_list_file(ali)
                elif stdin.startswith("d "):
                    aligo_download_file(ali, stdin.replace("d ", ""))
            return
    if upload_file_name != '':
        if upload_file_name.startswith("/"):
            print("Input a root path")
        else:
            upload_file_name = os.path.abspath(upload_file_name)
        print("Upload File:", upload_file_name)
        ali.upload_file(upload_file_name)
    if download_file_name != '':
        aligo_download_file(ali, download_file_name)


if __name__ == '__main__':
    main()
    sys.exit(0)
